package com.itheima.em.server.service.impl.tianditu;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.em.config.AMapServerConfig;
import com.itheima.em.config.EagleConfig;
import com.itheima.em.config.TMapServerConfig;
import com.itheima.em.enums.ProviderType;
import com.itheima.em.mapper.TraceMapper;
import com.itheima.em.pojo.Trace;
import com.itheima.em.server.config.MybatisPlusConfig;
import com.itheima.em.server.service.impl.amap.AMapWebApiService;
import com.itheima.em.service.EagleOrdered;
import com.itheima.em.service.TraceService;
import com.itheima.em.util.SnowflakeIdGenerator;
import com.itheima.em.vo.PageResult;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 天地图的轨迹管理实现
 */
@Service("TMapTraceService")
@ConditionalOnBean({TMapServerConfig.class, MybatisPlusConfig.class})
public class TMapTraceServiceImpl extends ServiceImpl<TraceMapper, Trace> implements TraceService {

    /**
     * 雪花ID生成器
     */
    public SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(this.getClass().hashCode()%31, this.getProvider().getValue()); // 创建雪花ID生成器，传入机器ID和数据中心ID
    
    @Resource
    private EagleConfig eagleConfig;
    @Resource
    private TMapWebApiService tMapWebApiService;

    /**
     * 创建轨迹
     *
     * @param serverId   服务id
     * @param terminalId 终端id
     * @param name       轨迹名称
     * @return 轨迹id
     */
    @Override
    public String create(Long serverId, Long terminalId, String name) {

        //轨迹ID
        Long traceId = idGenerator.generateId();
        
        //将服务数据存储到数据库
        Trace trace = new Trace();
        trace.setProvider(ProviderType.TMAP);
        trace.setServerId(serverId);
        trace.setName(name);
        trace.setTerminalId(terminalId);
        trace.setStatus(0);
        trace.setTraceId(traceId);
        trace.setStartTime(new Date());

        super.save(trace);
        return Convert.toStr(trace.getTraceId());
    }

    @Override
    public String delete(Long serverId, Long terminalId, Long traceId) {

        //删除数据库中的轨迹
        LambdaQueryWrapper<Trace> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Trace::getServerId, serverId);
        lambdaQueryWrapper.eq(Trace::getTerminalId, terminalId);
        lambdaQueryWrapper.eq(Trace::getTraceId, traceId);
        lambdaQueryWrapper.eq(Trace::getProvider, ProviderType.TMAP);
        return super.remove(lambdaQueryWrapper) ? "ok" : "err";
    }
    /**
     * 上传轨迹
     *
     * @param serverId   服务id
     * @param terminalId 终端id
     * @param traceId    轨迹id
     * @param pointList  轨迹点列表
     * @return
     */
    @Override
    public String upload(Long serverId, Long terminalId, Long traceId, List<Map<String, Object>> pointList) {
        //封装请求参数
        Map<String, Object> requestParam = new HashMap<>();
        requestParam.put("sid", serverId);
        requestParam.put("tid", terminalId);
        requestParam.put("trid", traceId);
        requestParam.put("points", JSONUtil.toJsonStr(pointList));
//TODO 实时更新上传轨迹点列表 到缓存数据库 【考虑环形数组结构】

//TODO 校验数据是否需要同步到数据库【每100个点同步一次数据库】
        return "ok";
    }

    /**
     * 停止运动，该方法会将轨迹中的轨迹点数据持久化本地数据库中
     *
     * @param serverId   服务id
     * @param terminalId 终端id
     * @param traceId    轨迹id
     * @param param      其他的请求参数
     * @return
     */
    @Override
    @Transactional
    public String stopTrace(Long serverId, Long terminalId, Long traceId, Map<String, Object> param) {
        //修改状态为停止运动
        LambdaQueryWrapper<Trace> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Trace::getServerId, serverId);
        lambdaQueryWrapper.eq(Trace::getTerminalId, terminalId);
        lambdaQueryWrapper.eq(Trace::getTraceId, traceId);
        lambdaQueryWrapper.eq(Trace::getProvider, ProviderType.TMAP);

        Trace trace = super.getOne(lambdaQueryWrapper);
        if (null == trace) {
            return null;
        }

//       TODO 同步缓存数据到 数据库

        trace.setEndTime(new Date());
        trace.setStatus(1);
        //更新的条件
        super.updateById(trace);

        return "ok";
    }

    /**
     * 分页查询轨迹列表，按照轨迹创建时间倒序排序
     *
     * @param page     页数
     * @param pageSize 页面大小
     * @return
     */
    @Override
    public PageResult<Trace> queryTracePageList(Integer page, Integer pageSize) {
        //TODO 分页查询不查询轨迹点信息，

        //分页构造器
        Page<Trace> pageInfo = new Page<>(page, pageSize);
        LambdaQueryWrapper<Trace> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Trace::getCreated);
        queryWrapper.eq(Trace::getProvider, ProviderType.TMAP);

        super.page(pageInfo, queryWrapper);

        return new PageResult().convert(pageInfo);
    }

    //查询轨迹点列表
    // 名称模糊查询
    // 轨迹id查询
    @Override
    public List<Trace> searchTraceList(Long traceId, String traceName) {

        LambdaQueryWrapper<Trace> queryWrapper = new LambdaQueryWrapper<>();
        if (null != traceId) {
            queryWrapper.eq(Trace::getTraceId, traceId);
        }
        if (StrUtil.isNotEmpty(traceName)) {
            queryWrapper.like(Trace::getName, traceName);
        }

        queryWrapper.eq(Trace::getProvider, ProviderType.TMAP);

        return super.list(queryWrapper);
    }

    /**
     * 查询轨迹详情，优先查询本地数据库，如本地库中没有数据，再查询地图服务商
     *
     * @param serverId   服务id
     * @param terminalId 终端id
     * @param traceId    轨迹id
     * @param param      其他的请求参数
     * @return
     */
    @Override
    public Trace queryTraceInfo(Long serverId, Long terminalId, Long traceId, Map<String, Object> param) {

        //查询持久化的数据,先查询轨迹数据
        LambdaQueryWrapper<Trace> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Trace::getServerId, serverId);
        lambdaQueryWrapper.eq(Trace::getTerminalId, terminalId);
        lambdaQueryWrapper.eq(Trace::getTraceId, traceId);
        lambdaQueryWrapper.eq(Trace::getProvider, ProviderType.TMAP);
        Trace trace = super.getOne(lambdaQueryWrapper);
        if (null == trace) {
            return null;
        }
        return trace;
    }



    @Override
    public int getOrder() {
        return EagleOrdered.ONE;
    }

    @Override
    public ProviderType getProvider() {
        return ProviderType.TMAP;
    }
}
